/**
 * Copyright [2012-2013] [Guðmundur Björn Birkisson]
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. Copyright [2012-2013] [Guðmundur Björn Birkisson]
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * ---------------------------------------------------------------------------
 * 
 * Class name:  KarelMain
 * 
 * Description of class:
 * 
 * Contains the main function of the program. It starts up the Morpho VM and
 * it in turn calls the UI.
 * 
 */

package karel;

import is.hi.cs.morpho.DebugInfo;
import is.hi.cs.morpho.Loader;
import is.hi.cs.morpho.Machine;
import is.hi.cs.morpho.Operation;
import java.io.DataInputStream;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.InflaterInputStream;
import javax.swing.UIManager;
import karel.UI.DebugWindow;

public class KarelMain {

    /**
     * Starts up the MorphoVM and runs mexe
     * @param mexe - Path to mexe to execute
     * @throws Exception 
     */
    static public void runMorphoVM(String mexe) throws Exception {
        Method mth = Loader.class.getDeclaredMethod("registerOps");
        mth.setAccessible(true);
        mth.invoke(null);

        Operation[] code = null;
        int pc;
        DataInputStream in = null;
        try {
            in = new DataInputStream(new InflaterInputStream(KarelMain.class.getResourceAsStream(mexe)));
            Loader loader = new Loader(in);
            pc = loader.loadInt();
            int n = loader.loadInt();
            code = new Operation[n];
            for (int i = 0; i != n; i++) {
                byte typecode = loader.loadByte();
                if (typecode == -128) {
                    code[i] = loader.loadOperation();
                } else {
                    code[i] = code[loader.loadInt()];
                }
            }
            DebugInfo d = new DebugInfo();
            try {
                d.load(loader);
                ///System.err.println("Debug info loaded");
            } catch (Exception e) {
                ///System.err.println("Failed to load debug info");
            }
            Machine.setDebugInfo(code, d);
        } finally {
            if (in == null) {
                System.err.println(mexe);
            } else {
                in.close();
            }
        }
        String args[] = new String[1];
        args[0] = "-i";
        Machine.args = args;
        new Machine(code, pc);
    }

    /**
     * Main function of the system
     * @param args 
     */
    public static void main(final String args[]) {
        //Attempt to use the standard look of the OS
        if (System.getProperty("os.name").startsWith("Windows")) {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                //Do Nothing, carry on!
            }
        } else if (System.getProperty("os.name").contains("Mac")) {
            System.setProperty("apple.laf.useScreenMenuBar", "true");
            System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Róbótinn Karel");
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (Exception e) {
                //Do Nothing, carry on!
            }
        }
        KarelSplashScreen.getInstance().setVisible(true);

        if (args.length > 0 && args[0].equals("-debug")) {
            DebugWindow.setDebugMode(true);
        }
        
        KarelSplashScreen.setProgressBarVal(10);
        
        try {
            runMorphoVM("morpho/KarelRunner.mexe");
        } catch (Exception ex) {
            Logger.getLogger(KarelMain.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
